#ifndef _DATA_PROCESSOR_HPP_
#define _DATA_PROCESSOR_HPP_

#include <ext/hash_map>
#include <stdint.h>
#include <cstdlib>
#include <cstdio>


template <typename RelationManager>
class DataProcessor
{
    __gnu_cxx::hash_map<uint32_t, uint32_t> _freq_map;
    RelationManager &_relations;
    const char *_file_path;


public:
    DataProcessor(const char *file_path, RelationManager &relations)
        : _file_path(file_path), _relations(relations)
    {
    }


    void AddFreq(uint32_t id) {
        _freq_map[id] ++;
    }

    void Process(uint32_t id1, uint32_t id2, uint32_t weight)
    {
        if (id1 == id2) {
            printf("WARNING: dumplicated item id %u\n", id1);
        }
        /*
        _freq_map[id1]++;
        _freq_map[id2]++;

        if (id1 < id2) {
        } else {
            uint32_t id3;
            id3 = id2;
            id2 = id1;
            id1 = id3;
        }
        */

        _relations.AddRelation(id1, id2, weight);
        _relations.AddRelation(id2, id1, weight);
    }

    /* write freq of each item into file */
    void Done()
    {
        char file_name[256];
        snprintf(file_name, 256, "%s/freqlist", _file_path);

        /* 
        format: item_count | reserved | id1 | count1 | id2 | count2 ....
        all are uint32_t, with the total size of (1 + item_count) * 2
        */

        __gnu_cxx::hash_map<uint32_t, uint32_t>::iterator it ;
        uint32_t item_count = _freq_map.size();
        
        uint32_t *num_buf = new uint32_t[2 * (item_count + 1)];
        num_buf[0] = item_count;
        uint32_t pos = 2;

        for(it = _freq_map.begin(); it != _freq_map.end(); it++) {
            num_buf[pos++] = it->first; //item id
            num_buf[pos++] = it->second; //item freq
        }
            

        FILE *f = fopen(file_name, "wb");
        fwrite(num_buf, 4, 2 * (item_count + 1), f);
        fclose(f);
        delete[] num_buf;
    }
};

class FreqReader
{
    __gnu_cxx::hash_map<uint32_t, uint32_t> _freq_map;


public:
    FreqReader()
    {
    }


    uint32_t GetFreq(uint32_t id)
    {
        __gnu_cxx::hash_map<uint32_t, uint32_t>::iterator it = 
            _freq_map.find(id);
        if (it == _freq_map.end()) {
            printf("ERROR: no freq for %u\n", id);
            return 0;
        } else
            return it->second;
    }

    int Read(const char *file_path)
    {
        char file_name[256];
        snprintf(file_name, 256, "%s/freqlist", file_path);
        uint32_t header[2];
        uint32_t *buf;

        FILE *f = fopen(file_name, "rb");
        if (f == NULL)
            return -1;

        fread(header, 4, 2, f);
        buf = new uint32_t[2 * header[0]];
        fread(buf, 4, 2 * header[0], f);

        for(uint32_t i = 0; i < header[0]; i++) {
            _freq_map[buf[2 * i]] = buf[2 * i + 1];
        }

        fclose(f);
        delete []buf;
    }
};

#endif 

